package com.ailanyin.admin.modules.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ailanyin.admin.modules.system.mapper.*;
import com.ailanyin.admin.modules.system.model.SysPost;
import com.ailanyin.admin.modules.system.model.SysUserPost;
import com.ailanyin.admin.modules.system.model.SysUserRole;
import com.ailanyin.admin.modules.system.service.SysFileService;
import com.ailanyin.admin.modules.system.service.SysUserService;
import com.ailanyin.common.annotation.DataScope;
import com.ailanyin.common.exception.Asserts;
import com.ailanyin.common.model.SysRole;
import com.ailanyin.common.model.SysUser;
import com.ailanyin.security.model.LoginUser;
import com.ailanyin.security.service.SecurityUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author ailanyin
 * @version 1.0
 * @since 2021/10/15 0015 下午 14:23
 */
@Service
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class SysUserServiceImpl implements SysUserService {


    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private SecurityUserService securityUserService;
    @Autowired
    private SysFileService sysFileService;
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysRoleMapper roleMapper;
    @Resource
    private SysPostMapper postMapper;
    @Resource
    private SysUserPostMapper userPostMapper;
    @Resource
    private SysUserRoleMapper userRoleMapper;


    /**
     * 获取当前登录的用户信息
     *
     * @return sysUser
     */
    @Override
    public SysUser getCurrentUser() {
        try {
            SecurityContext ctx = SecurityContextHolder.getContext();
            Authentication auth = ctx.getAuthentication();
            LoginUser adminUserDetails = (LoginUser) auth.getPrincipal();
            return adminUserDetails.getUser();
        } catch (Exception e) {
            return new SysUser();
        }
    }

    /**
     * 根据条件分页查询已分配用户角色列表
     *
     * @param user 查询条件
     * @return 用户集合
     */
    @Override
    public List<SysUser> selectAllocatedList(SysUser user) {
        return userMapper.selectAllocatedList(user);
    }

    /**
     * 新增用户
     *
     * @param user user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUser(SysUser user) {
        if (checkUserNameNotUnique(user.getUserName())) {
            Asserts.fail("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        }

        if (StrUtil.isNotBlank(user.getPassword())) {
            //加密密码
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        }

        user.setCreateTime(new Date());
        user.setCreateBy(getCurrentUser().getUserName());
        // 新增用户信息
        int row = userMapper.insertUser(user);
        if (row == 0) {
            return row;
        }

        if (ArrayUtil.isNotEmpty(user.getPostIds())) {
            // 新增用户岗位关联
            insertUserPost(user);
        }

        if (ArrayUtil.isNotEmpty(user.getRoleIds())) {
            // 新增用户与角色管理
            insertUserRole(user);
        }
        return row;
    }

    /**
     * 新增用户岗位信息
     *
     * @param user user
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertUserPost(SysUser user) {
        Long[] posts = user.getPostIds();
        if (ArrayUtil.isNotEmpty(posts)) {
            // 新增用户与岗位管理
            List<SysUserPost> list = new ArrayList<>();
            for (Long postId : posts) {
                SysUserPost up = new SysUserPost();
                up.setUserId(user.getUserId());
                up.setPostId(postId);
                list.add(up);
            }
            if (list.size() > 0) {
                userPostMapper.batchUserPost(list);
            }
        }
    }

    /**
     * 新增用户角色信息
     *
     * @param user 用户对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertUserRole(SysUser user) {
        Long[] roles = user.getRoleIds();
        if (ArrayUtil.isNotEmpty(roles)) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<>();
            for (Long roleId : roles) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(user.getUserId());
                ur.setRoleId(roleId);
                list.add(ur);
            }
            if (list.size() > 0) {
                userRoleMapper.batchUserRole(list);
            }
        }
    }

    /**
     * 校验用户名称是否不唯一
     *
     * @param userName 用户名称
     * @return 结果
     */
    @Override
    public boolean checkUserNameNotUnique(String userName) {
        return userMapper.checkUserNameUnique(userName) > 0;
    }

    /**
     * 更新用户信息
     *
     * @param user user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateUser(SysUser user) {
        checkUserAllowed(user);
        int row = userMapper.updateUser(user);
        if (row == 0) {
            return row;
        }
        Long userId = user.getUserId();
        if (ArrayUtil.isNotEmpty(user.getPostIds())) {
            // 删除用户与岗位关联
            userPostMapper.deleteUserPostByUserId(userId);
            // 新增用户与岗位管理
            insertUserPost(user);
        }

        if (ArrayUtil.isNotEmpty(user.getRoleIds())) {
            // 删除用户与角色关联
            userRoleMapper.deleteUserRoleByUserId(userId);
            // 新增用户与角色管理
            insertUserRole(user);
        }

        delUserDetails(user);
        user.setUpdateTime(new Date());
        user.setUpdateBy(getCurrentUser().getUserName());
        return row;
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    @Override
    public void checkUserAllowed(SysUser user) {
        if (ObjectUtil.isNotEmpty(user.getUserId()) && user.isAdmin()) {
            Asserts.fail("不允许操作超级管理员用户");
        }
    }

    /**
     * 批量删除用户
     *
     * @param userIds ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserByIds(Long[] userIds) {
        for (Long userId : userIds) {
            checkUserAllowed(new SysUser(userId));
        }
        // 删除用户与角色关联
        userRoleMapper.deleteUserRole(userIds);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPost(userIds);
        // 删除用户
        userMapper.deleteUserByIds(userIds);
        // 删除userDetailsMap中的数据
        for (Long userId : userIds) {
            SysUser sysUser = userMapper.selectUserById(userId);
            delUserDetails(sysUser);
        }
    }

    /**
     * 重置密码
     *
     * @param user user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int resetPwd(SysUser user) {
        delUserDetails(user);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userMapper.updateUser(user);
    }

    /**
     * 修改状态
     *
     * @param user user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateUserStatus(SysUser user) {
        checkUserAllowed(user);
        delUserDetails(user);
        return userMapper.updateUser(user);
    }

    /**
     * 通过 id 查询
     *
     * @param userId userId
     * @return return
     */
    @Override
    public SysUser selectUserById(Long userId) {
        return userMapper.selectUserById(userId);
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertUserAuth(Long userId, Long[] roleIds) {
        userRoleMapper.deleteUserRoleByUserId(userId);
        insertUserRole(userId, roleIds);
    }

    /**
     * 校验用户是否有数据权限
     *
     * @param userId 用户id
     */
    @Override
    public void checkUserDataScope(Long userId) {
        if (!getCurrentUser().isAdmin()) {
            SysUser user = new SysUser();
            user.setUserId(userId);
            List<SysUser> users = userMapper.selectUserList(user);
            if (CollectionUtil.isEmpty(users)) {
                Asserts.fail("没有权限访问用户数据！");
            }
        }
    }

    /**
     * 根据条件分页查询用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUser user) {
        return userMapper.selectUserList(user);
    }

    /**
     * 新增用户角色信息
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertUserRole(Long userId, Long[] roleIds) {
        if (ArrayUtil.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<SysUserRole>();
            for (Long roleId : roleIds) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                list.add(ur);
            }
            if (list.size() > 0) {
                userRoleMapper.batchUserRole(list);
            }
        }
    }

    /**
     * 根据条件分页查询未分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUnallocatedList(SysUser user) {
        return userMapper.selectUnallocatedList(user);
    }

    /**
     * 通过用户名查询用户
     *
     * @param userName 用户名
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserByUserName(String userName) {
        return userMapper.selectUserByUserName(userName);
    }

    /**
     * 导入用户列表
     *
     * @param list          用户列表
     * @param updateSupport 是否更新已经存在的数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importData(List<SysUser> list, boolean updateSupport) {
        list.stream()
                .filter(sysUser -> StrUtil.isNotBlank(sysUser.getUserName()))
                .forEach(sysUser -> {
                    //更新已经存在的用户
                    if (updateSupport) {
                        //说明存在
                        SysUser userByUserName = userMapper.selectUserByUserName(sysUser.getUserName());
                        if (ObjectUtil.isNotEmpty(userByUserName)) {
                            sysUser.setUserId(userByUserName.getUserId());
                            updateUser(sysUser);
                        } else {
                            insertUser(sysUser);
                        }
                    } else {
                        if (checkUserNameNotUnique(sysUser.getUserName())) {
                            Asserts.fail("登录账号: " + sysUser.getUserName() + " 已经存在,导入失败！");
                        }

                        insertUser(sysUser);
                    }
                });

    }

    /**
     * 已删除用户列表
     *
     * @param user user
     * @return list
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectDeleteUserList(SysUser user) {
        return userMapper.selectDeleteUserList(user);
    }

    /**
     * 恢复已删除的用户
     *
     * @param ids ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recoveryDeleteUser(List<Long> ids) {
        userMapper.recoveryDeleteUser(ids);
    }

    /**
     * 彻底删除用户
     *
     * @param ids ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void realDeleteUser(List<Long> ids) {
        userMapper.realDeleteUser(ids);
    }

    /**
     * 查询用户所属角色组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserRoleGroup(String userName) {
        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
        StringBuilder idsStr = new StringBuilder();
        for (SysRole role : list) {
            idsStr.append(role.getRoleName()).append(",");
        }
        if (StrUtil.isNotBlank(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }
        return idsStr.toString();
    }

    /**
     * 查询用户所属岗位组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserPostGroup(String userName) {
        List<SysPost> list = postMapper.selectPostsByUserName(userName);
        StringBuilder idsStr = new StringBuilder();
        for (SysPost post : list) {
            idsStr.append(post.getPostName()).append(",");
        }
        if (StrUtil.isNotBlank(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }
        return idsStr.toString();
    }

    /**
     * 用户自主修改基本信息
     *
     * @param user user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProfile(SysUser user) {
        SysUser currentUser = getCurrentUser();
        user.setUserId(currentUser.getUserId());
        user.setUpdateTime(new Date());
        user.setUpdateBy(currentUser.getUserName());
        userMapper.updateUser(user);
        delUserDetails(user);
    }

    /**
     * 用户自主修改密码
     *
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePwd(String oldPassword, String newPassword) {
        SysUser user = getCurrentUser();
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            Asserts.fail("旧密码错误！");
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        userMapper.resetUserPwd(user.getUserName(), user.getPassword());
        delUserDetails(user);
    }

    /**
     * 更新头像
     *
     * @param file file
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAvatar(MultipartFile file) {
        String fileUrl = sysFileService.fileUpload(file);
        SysUser user = getCurrentUser();
        user.setAvatar(fileUrl);
        userMapper.updateUserAvatar(user.getUserName(), user.getAvatar());
        delUserDetails(user);
    }

    /**
     * 删除UserDetailsMap中的数据
     *
     * @param user user
     */
    private void delUserDetails(SysUser user) {
        if (StrUtil.isBlank(user.getUserName())) {
            user.setUserName(userMapper.selectUserById(user.getUserId()).getUserName());
        }
        securityUserService.delUserDetailsFromCache(user.getUserName());
    }
}
